﻿using System;
using System.Collections.Generic;
using System.Threading;
using System.Drawing;
using Clandestine.Battle;
using Clandestine.Battle.Enemies;
using Clandestine.Entities;

namespace Clandestine
{
    public static class WorldMap
    {
        private static Thread worldMapThread;
        private static bool worldMapThreadRunning = false;

        public static Random Rand = new Random((int)System.DateTime.Now.Millisecond);
        public static Level Level = null;

        public static MapPlayer Player = null;

        public static bool Paused = false;

        public static void Start()
        {
            worldMapThread = new Thread(new ThreadStart(threadProc));
            worldMapThread.Start();
        }

        private static void threadProc()
        {
            worldMapThreadRunning = true;
            bool w = false; // don't let use spam happen

            while (Program.Running)
            {
                if (!Paused && Player != null)
                {
                    Rectangle playerRectangle = new Rectangle(
                        Point.Round(Player.Position),
                        Player.Size);

                    // OnCollide...
                    Collision.TryTriggerCollideEvent(playerRectangle);

                    if (Keyboard.IsPressed(Key.Menu))
                        debugStartBattle();

                    if (!Keyboard.IsPressed(Key.Select))
                        w = false;

                    // OnUse...
                    if (!w && Keyboard.IsPressed(Key.Select))
                        if (Collision.TryTriggerUseEvent(playerRectangle))
                            w = true;
                }

                //
                // TODO: Who knows?
                //

                // Sleep.
                Thread.Sleep(20);
            }

            worldMapThreadRunning = false;
        }

        public static void Stop()
        {
            Thread.Sleep(50); // would rather not abort unless we have to,
                              // so let's give it a chance!

            if (worldMapThreadRunning)
                // sigh...
                worldMapThread.Abort();
        }

        // Should this rly be filename?
        public static void ChangeLevel(string filename)
        {
            ChangeLevel(filename, string.Empty);
        }
        public static void ChangeLevel(string filename, string entranceName)
        {
            // pause rendering so we don't see the loading of the level!
            Graphics.PauseRendering = true;

            // change level
            Level.Destroy();
            Level = Level.GetLevel(filename);
            
            // find entrance on tuther side!
            Point pos = new Point();
            try
            {
                // no entrance?
                if (entranceName == string.Empty)
                    throw new Exception();

                // get entrance
                Entity e = WorldMap.Level.Entities.GetByName(entranceName);
                if (e.GetType().IsSubclassOf(typeof(Clandestine.Entities.Entrance)) || e.GetType() == typeof(Clandestine.Entities.Entrance))
                {
                    // pos = new Point(e.Position.X + (e.Size.Width / 2) - (WorldMap.Player.Width / 2), e.Position.Y + e.Size.Height - WorldMap.Player.Height - 1);
                    
                    // figure out which way we should be pointing and orientate appropriately
                    switch(((Clandestine.Entities.Entrance)e).EntranceDirection)
                    {
                        case Direction.Up:
                            pos.X = e.Position.X + (e.Size.Width / 2) - (WorldMap.Player.Width / 2);
                            pos.Y = e.Position.Y + e.Size.Height - WorldMap.Player.Height - 1;
                            // todo: set direction
                            break;
                        case Direction.Down:
                            pos.X = e.Position.X + (e.Size.Width / 2) - (WorldMap.Player.Width / 2);
                            pos.Y = e.Position.Y + 1;
                            break;
                        case Direction.Left:
                            pos.X = e.Position.X + (e.Size.Width / 2) - (WorldMap.Player.Width / 2);
                            pos.Y = e.Position.Y + (e.Size.Height / 2) - (WorldMap.Player.Height / 2);
                            break;
                        case Direction.Right:
                            pos.X =  e.Position.X - (e.Size.Width / 2) + (WorldMap.Player.Width / 2);
                            pos.Y = e.Position.Y + (e.Size.Height / 2) - (WorldMap.Player.Height / 2);
                            break;
                    }
                }
                 
                else
                    throw new Exception(); // so the catch is called (catch is also for ArgumentOutOfRange exception from .GetByName())
            }
            catch (Exception e)
            {
                pos = new Point(0, 0);
                Log.e("Could not find entrance, setting to (0,0).");
            }

            // set position!
            WorldMap.Player.Position = pos;
            Camera.UpdateScrolling(pos);

            // unpause
            Graphics.PauseRendering = false;
        }

        private static void debugStartBattle()
        {
                List<Enemy> enemies = new List<Enemy>() {
                            new EvilOscar(),
                            new BadassMotherfucker(),
                            new EvilOscar()
                        };
                BattleController.StartBattle(BattleType.Ambush, Player.Party, enemies);
        }
    }
}
